#include <multitasking.h>
#include <printThings.h>
#include <ports.h>
#include <mytime.h>

Task tasks[MAX_TASKS];
int aktTask, avTasks;

unsigned int scheduler(unsigned int aktStackAddr) {
    asm volatile("cli");
    timerHandler();

    if (avTasks == 0) {
        outb(0x20, 0x20);
        outb(0xA0, 0x20);
        return aktStackAddr;
    }

    //printf("task: %d avTasks:%d\n", aktTask, avTasks);

    //asm volatile("mov %0, %%cr3" : : "r" (tasks[aktTask].vAddr.pageDirectory));
    tasks[aktTask].stack = aktStackAddr;
    aktTask++;

    if (aktTask == avTasks)
        aktTask = 0;
asm volatile("mov %0, %%cr3" : : "r" (tasks[aktTask].vAddr.pageDirectory));

    outb(0x20, 0x20);
    outb(0xA0, 0x20);
    //printf("switching to task: %d avTasks:%d Stack:%y\n", aktTask, avTasks, tasks[aktTask].stack);
    if (aktTask == 2) {
        //memDump(0x900044, &tasks[aktTask].vAddr);
        //asm volatile("cli");
        //asm volatile("sti");
    }

    return tasks[aktTask].stack;
}

void changePageDir() {
asm volatile( "mov %0, %%cr3" : : "r" (tasks[aktTask].vAddr.pageDirectory) );
}

void exitProgramm(){
    
}

void initTask(unsigned int entry, struct kernelPagingStructure vAddr, unsigned int stack) {
    asm volatile("cli");

    //printf("stack: %y, avTask:%d\n", stack, avTasks);
    int buf = 2;
    tasks[avTasks].pid = avTasks;
    tasks[avTasks].stack = stack;
    tasks[avTasks].state = BUSY;
    tasks[avTasks].vAddr = vAddr;

    //printf("[%y][%y]\n", vAddr.pageTable[2][767], entry);

    unsigned long *stackbuf = (unsigned long *)tasks[avTasks].stack - 1;

    /*fuer iret*/
    *(--stackbuf) = buf;
    *(--stackbuf) = buf;
    *(--stackbuf) = 0x0202;
    *(--stackbuf) = 0x08;
    *(--stackbuf) = entry;

    *(--stackbuf) = 0;
    *(--stackbuf) = 0;
    *(--stackbuf) = 0;
    *(--stackbuf) = 0;
    *(--stackbuf) = 0;
    *(--stackbuf) = 0;
    *(--stackbuf) = 0;

    /*die segmentregister auf den stack legen*/
    *(--stackbuf) = 0x10;
    *(--stackbuf) = 0x10;
    *(--stackbuf) = 0x10;
    *(--stackbuf) = 0x10;

    tasks[avTasks].stack = stackbuf;
    //if(stackbuf > (0x900000 + 0x200000))
    //tasks[avTasks].stack -= 0x200000;

    //printf("%y\n", tasks[avTasks].stack);

    //printf("taskAngelegt\n");

    avTasks++;
    aktTask = 0;

    asm volatile("sti");
}

void initMultitasking() {
    int i;

    for (i = 0; i < MAX_TASKS; i++) {
        tasks[i].state = READY;
    }

    aktTask = avTasks = 0;


    asm volatile("cli");
    /*init KernelTask*/
    tasks[aktTask].pid = avTasks;
    tasks[aktTask].stack = 0;
    tasks[aktTask].state = BUSY;
    tasks[aktTask].vAddr = getKernelPagingStruct();
    avTasks++;
    asm volatile("sti");
}
